package org.rapan.EJB;

import java.util.Collections;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import org.rapan.Position;
import org.rapan.exceptions.DateMismatchException;
import org.rapan.exceptions.EmailTakenException;
import org.rapan.exceptions.InvalidLoginException;
import org.rapan.jpa.Consultant;

@Stateless
public class ConsultantBean implements ConsultantInt {

	@PersistenceContext(unitName = "Consult")
	private EntityManager em;

	@Override
	public Consultant register(String name, String email, Position position,
			Date startDate, String password) throws EmailTakenException {
		TypedQuery<Long> q = em.createQuery(
				"Select count(c) from Consultant c where c.email = :email",
				Long.class);
		q.setParameter("email", email);
		if (q.getSingleResult() > 0)
			throw new EmailTakenException();
		Consultant c = new Consultant();
		c.setEmail(email);
		c.setFullName(name);
		c.setPosition(position);
		c.setStartDate(startDate);
		c.setPassword(password);
		em.persist(c);
		em.flush();
		em.refresh(c);
		return c;

	}

	@Override
	public Consultant login(String email, String password)
			throws InvalidLoginException {
		Consultant c;
		TypedQuery<Consultant> q = em
				.createQuery(
						"Select c from Consultant c where c.email = :email and c.password = :password",
						Consultant.class);
		q.setParameter("email", email);
		q.setParameter("password", password);
		try {
			c = q.getSingleResult();
		} catch (NoResultException e) {
			c = null;
		}
		if (c == null)
			throw new InvalidLoginException();
		return c;
	}

	@Override
	public Consultant view(long id) {
		try {
			Consultant c = em.find(Consultant.class, id);
			return c;
		} catch (IllegalArgumentException e) {
			return null;
		}
	}

	@Override
	public Consultant edit(Consultant consultant) throws DateMismatchException {
		if ( consultant.getEndDate() != null && consultant.getEndDate().before(consultant.getStartDate()))
			throw new DateMismatchException();
		Consultant c = em.find(Consultant.class, consultant.getId());
		c.setEmail(consultant.getEmail());
		c.setFullName(consultant.getFullName());
		c.setEndDate(consultant.getEndDate());
		c.setStartDate(consultant.getStartDate());
		c.setPassword(consultant.getPassword());
		c.setPosition(consultant.getPosition());
		em.merge(c);
		em.flush();
		em.refresh(c);
		return c;
	}

	@Override
	public Set<Consultant> getAllConsultants() {
		TypedQuery<Consultant> q = em.createQuery("From Consultant",
				Consultant.class);
		Set<Consultant> conSet = new TreeSet<Consultant>();
		conSet.addAll(q.getResultList());
		return conSet;
	}

	@Override
	public void checkAndCreateAdmin() {
		TypedQuery<Long> q = em.createQuery(
				"Select count(c) from Consultant c", Long.class);
		if (q.getSingleResult() == 0)
			try {
				register("admin", "admin@pasoft.co.uk", Position.Admin,
						new Date(), "admin");
			} catch (EmailTakenException e) {
				System.out.println("WTF?!");
			}

	}

	@Override
	public Set<Consultant> findConsultants(String match) {
		Set<Consultant> conSet = new TreeSet<Consultant>();
		TypedQuery<Consultant> q = em
				.createQuery(
						"Select c from Consultant c where c.fullName like :match or c.email like :match and c.position <> :admin",
						Consultant.class);
		if ("*".equalsIgnoreCase(match))
			q.setParameter("match", "%");
		else
			q.setParameter("match", "%" + match + "%");
		q.setParameter("admin", Position.Admin);
		try {
			conSet.addAll(q.getResultList());
		} catch (NoResultException e) {
			return Collections.emptySet();
		}

		return conSet;
	}

}
